#include "bigrama.h"
#include "trigrama.h"
estructuraAuxiliar bigrama::estructuraAsociada;
estructuraAuxiliar bigrama::estructuraAsociadaOrdenadaPorSegundoTermino;


const char* bigrama::RUTA_ARCHIVO_BIGRAMAS="Bigramas.txt";

const char* bigrama::RUTA_ARCHIVO_BIGRAMAS_REORDENADOS="Bigramas-Reordenados.txt";


bigrama::bigrama()
{

}

bigrama::bigrama(string termino1,string termino2)
{
	//notar que este constructor funciona si los terminos proceden de un vector de strings y son cosecutivos
    this->tupla = &termino1;
    this->nTerminos=2;
    bigrama::estructuraAsociada.ngramas=this->nTerminos;

	bigrama::estructuraAsociadaOrdenadaPorSegundoTermino.ngramas=this->nTerminos;
	bigrama::estructuraAsociadaOrdenadaPorSegundoTermino.especificacion="reordenados";

    bigrama::estructuraAsociada.add(this->representacionComoString());
    bigrama::estructuraAsociadaOrdenadaPorSegundoTermino.add(this->representacionReordenada());
}

bigrama::~bigrama()
{
    //dtor
}

/*void bigrama::crearArchivosUnificados()
{
	//2 KWAY MERGEs

}*/


void bigrama::setearMaximaCantidadEnEstructurasAsociadas(int maxNGramas)
{
	bigrama::estructuraAsociada.nroMaximoDeNGramasPermitidos=maxNGramas;
	bigrama::estructuraAsociadaOrdenadaPorSegundoTermino.nroMaximoDeNGramasPermitidos=maxNGramas;
}

bigrama* bigrama::bigramasDeTupla(Tupla tupla)
{
	bigrama* tmp= new bigrama[tupla.nroDeTerminos-1];

	for (int i=0;i<tupla.nroDeTerminos-1;i++)
	{
		tmp[i].tupla = &tupla.tuplaDeTerminos[i];
	}

	return tmp;
}


void bigrama::agregarBigramasDeTupla(Tupla tupla){

	for (int i=0;i<tupla.nroDeTerminos-1;i++)
		{
			new bigrama(tupla.tuplaDeTerminos[i],tupla.tuplaDeTerminos[i+1]);
		}

}


string bigrama::representacionReordenada()
{
	return (this->tupla[1]+" "+this->tupla[0]);
}

void bigrama::instertarBigramasDeTupla(Tupla tupla)
{


	for (int i=0;i<tupla.nroDeTerminos-1;i++)
			{
			bigrama tmp;
			tmp.nTerminos=2;
			tmp.tupla=&tupla.tuplaDeTerminos[i];
			bigrama::estructuraAsociada.ngramas=2;
			bigrama::estructuraAsociada.add(tmp.representacionComoString());
			bigrama::estructuraAsociadaOrdenadaPorSegundoTermino.ngramas=2;
			bigrama::estructuraAsociadaOrdenadaPorSegundoTermino.especificacion="reordenados";

			bigrama::estructuraAsociadaOrdenadaPorSegundoTermino.add(tmp.representacionReordenada());

			}

}

void bigrama::dumpEstructurasAsociadas()
{
	bigrama::estructuraAsociada.dump();
	bigrama::estructuraAsociadaOrdenadaPorSegundoTermino.dump();
}

void bigrama::recolectarDatosDeTrigramas()
{
	bigrama::recolectarDatosDeTrigramasDesdeArchivo();
}

void bigrama::recolectarDatosDeTrigramasDesdeArchivo()
{
	Parser par;
	if (!par.cargarArchivo(trigrama::RUTA_ARCHIVO_TRIGRAMAS))
	{
		unsigned long int bigramasEnArchivo,distintosConFreq1,distintosConFreq2,distintosConFreq2oMas;
		bigramasEnArchivo=distintosConFreq1=distintosConFreq2=distintosConFreq2oMas=0;
		bool finArch=false;

		string nombreDeArchivoEnUso=bigrama::estructuraAsociada.obtenerSiguienteNombreDeArchivo(bigrama::estructuraAsociada.archivosRestantesAUnificar);
		std::ofstream  fs(nombreDeArchivoEnUso.c_str());
		bigrama::estructuraAsociada.archivosRestantesAUnificar++;



		Tupla trigramaConFreq =par.cargarSiguienteLinea();
		if((trigramaConFreq.nroDeTerminos>0)&&(trigramaConFreq.tuplaDeTerminos[0]!=""))
		{


			while(!par.archivoProcesado())
			{
				Tupla  posibleNuevoTrigrama;

				while((!(finArch=par.archivoProcesado()))&&(!((posibleNuevoTrigrama=par.cargarSiguienteLinea()).compareTo(trigramaConFreq,2))))
				{
					unsigned long int freqTrigrama=(unsigned long int) atol(posibleNuevoTrigrama.tuplaDeTerminos[3].c_str());

					switch(freqTrigrama)
					{
						case 1:
						{
							distintosConFreq1++;
							break;
						}

						case 2:
						{
							distintosConFreq2++;
							break;
						}

						default :
						{
							distintosConFreq2oMas++;
							break;
						}
					}


					//delete posibleNuevoTrigrama;

				}

				if(!finArch)
				{
					unsigned long int freqTrigrama=(unsigned long int) atol(trigramaConFreq.tuplaDeTerminos[3].c_str());

					switch(freqTrigrama)
					{
						case 1:
								{
								distintosConFreq1++;
								break;
								}
						case 2:
								{
								distintosConFreq2++;
								break;
								}
						default:
								{
								distintosConFreq2oMas++;
								break;
								}
					}


					fs << bigrama::construirRepresentacion(trigramaConFreq.tuplaDeTerminos[0],trigramaConFreq.tuplaDeTerminos[1],0,distintosConFreq1,distintosConFreq2,distintosConFreq2oMas) << std::endl;
					bigramasEnArchivo++;
					//delete trigramaConFreq;
					distintosConFreq1=distintosConFreq2=distintosConFreq2oMas=0;
				}

				if(bigramasEnArchivo>=bigrama::estructuraAsociada.nroMaximoDeNGramasPermitidos)
				{
					fs.close();
					//delete fs;


					nombreDeArchivoEnUso=bigrama::estructuraAsociada.obtenerSiguienteNombreDeArchivo(bigrama::estructuraAsociada.archivosRestantesAUnificar);
					std::ofstream fs (nombreDeArchivoEnUso.c_str());
					bigrama::estructuraAsociada.archivosRestantesAUnificar++;
					bigramasEnArchivo=0;
				}

				trigramaConFreq=posibleNuevoTrigrama;
			}
			//delete trigramaConFreq;
		}

		par.cerrarArchivo();

		fs.close();
		//delete fs;
		if(bigramasEnArchivo==0)
			{
			remove(nombreDeArchivoEnUso.c_str());
			bigrama::estructuraAsociada.archivosRestantesAUnificar--;
			}
	}
}


/*void bigrama::recolectarDatosDeTrigramasDesdeEstructura()
{
		unsigned long int distintosConFreq1,distintosConFreq2,distintosConFreq2oMas;
		distintosConFreq1=distintosConFreq2=distintosConFreq2oMas=0;


		Tupla* trigramaConFreq =par.cargarSiguienteLinea();
		if((trigramaConFreq->nroDeTerminos>0)&&(trigramaConFreq.tuplaDeTerminos[0]!=""))
		{


			while(!par.archivoProcesado())
			{
				Tupla * posibleNuevoTrigrama;

				while((!(finArch=par.archivoProcesado()))&&(!((posibleNuevoTrigrama=par.cargarSiguienteLinea())->compareTo(trigramaConFreq,2))))
				{
					unsigned long int freqTrigrama=(unsigned long int) atol(posibleNuevoTrigrama.tuplaDeTerminos[3].c_str());

					switch(freqTrigrama)
					{
						case 1:
						{
							distintosConFreq1++;
							break;
						}

						case 2:
						{
							distintosConFreq2++;
							break;
						}

						default :
						{
							distintosConFreq2oMas++;
							break;
						}
					}


					delete posibleNuevoTrigrama;

				}

				if(!finArch)
				{
					unsigned long int freqTrigrama=(unsigned long int) atol(trigramaConFreq.tuplaDeTerminos[3].c_str());

					switch(freqTrigrama)
					{
						case 1:
								{
								distintosConFreq1++;
								break;
								}
						case 2:
								{
								distintosConFreq2++;
								break;
								}
						default:
								{
								distintosConFreq2oMas++;
								break;
								}
					}


					*fs << bigrama::construirRepresentacion(trigramaConFreq.tuplaDeTerminos[0],trigramaConFreq.tuplaDeTerminos[1],0,distintosConFreq1,distintosConFreq2,distintosConFreq2oMas) << std::endl;
					bigramasEnArchivo++;
					delete trigramaConFreq;
					distintosConFreq1=distintosConFreq2=distintosConFreq2oMas=0;
				}

				if(bigramasEnArchivo>=bigrama::estructuraAsociada.nroMaximoDeNGramasPermitidos)
				{
					fs->close();
					delete fs;


					nombreDeArchivoEnUso=bigrama::estructuraAsociada.obtenerSiguienteNombreDeArchivo(bigrama::estructuraAsociada.archivosRestantesAUnificar);
					fs = new std::ofstream(nombreDeArchivoEnUso.c_str());
					bigrama::estructuraAsociada.archivosRestantesAUnificar++;
					bigramasEnArchivo=0;
				}

				trigramaConFreq=posibleNuevoTrigrama;
			}
			delete trigramaConFreq;
		}

		par.cerrarArchivo();

		fs->close();
		delete fs;
		if(bigramasEnArchivo==0)
			{
			remove(nombreDeArchivoEnUso.c_str());
			bigrama::estructuraAsociada.archivosRestantesAUnificar--;
			}

}
*/

std::string bigrama::construirRepresentacion(string termino1, string termino2, unsigned long int freq, unsigned long int distintosConFreq1, unsigned long int distintosConFreq2, unsigned long int distintosConFreq2oMas)
{
	const int n=snprintf(NULL,0,"%lu",freq);
	char buf1[n+1];
	snprintf(buf1,n+1,"%lu",freq);

	const int m=snprintf(NULL,0,"%lu",distintosConFreq1);
	char buf2[m+1];
	snprintf(buf2,m+1,"%lu",distintosConFreq1);


	const int o=snprintf(NULL,0,"%lu",distintosConFreq2);
	char buf3[o+1];
	snprintf(buf3,o+1,"%lu",distintosConFreq2);

	const int p=snprintf(NULL,0,"%lu",distintosConFreq2oMas);
	char buf4[p+1];
	snprintf(buf4,p+1,"%lu",distintosConFreq2oMas);


return termino1+" "+termino2+" "+(std::string)buf1+" "+(std::string)buf2+" "+(std::string)buf3+" "+(std::string)buf4;
}
